package org.finmanager.statistics;

import com.alee.extended.panel.WebButtonGroup;
import com.alee.laf.button.WebButton;

import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import static org.finmanager.core.Constants.DATE_FORMAT_MONTH;

/**
 * Created by Kelvin on 13/4/2014.
 */

//The UI of the statistic HeatMap distribution table function
public class ItemDistributionUI {
	JPanel mainPanel = new JPanel(new BorderLayout(0, 0));

	//Buttons to allow user to go to current/next/previous month in the middle on top of the chart
	WebButton increaseMonthButton = new WebButton(">");
	WebButton decreaseMonthButton = new WebButton("<");
	WebButton setCurrentMonthButton = new WebButton();

	//Setting the appearance of the table
	public ItemDistributionUI(ItemDistributionController itemDistributionController) {
		JTable table = new JTable(itemDistributionController.getItemDistributionModel());

		TableColumnModel columnModel = table.getColumnModel();
		for (int i = 0; i < columnModel.getColumnCount(); i++) {
			if (i == 0)
				columnModel.getColumn(i).setPreferredWidth(120);
			else
				columnModel.getColumn(i).setPreferredWidth(35);
		}

		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setSelectionModel(new NullSelectionModel());
		table.setDefaultRenderer(Double.class, new HeatMapCellRenderer());

		table.getTableHeader().setResizingAllowed(false);
		table.getTableHeader().setReorderingAllowed(false);

		table.setRowHeight(24);

		table.setShowGrid(false);
		table.setIntercellSpacing(new Dimension(0,0));

		//Because each month has around 30 days showing horizontally
		//A Scroll is needed to in the UI
		JScrollPane scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollPane.setBorder(BorderFactory.createEmptyBorder());
		scrollPane.setFocusable(false);

		increaseMonthButton.setActionCommand(ItemDistributionController.INCREASE_MONTH);
		decreaseMonthButton.setActionCommand(ItemDistributionController.DECREASE_MONTH);
		setCurrentMonthButton.setActionCommand(ItemDistributionController.SET_CURRENT_MONTH);
		WebButtonGroup controlButtonGroup = new WebButtonGroup(decreaseMonthButton, setCurrentMonthButton, increaseMonthButton);
		controlButtonGroup.setButtonsDrawFocus(false);
		JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		controlPanel.add(controlButtonGroup);

		getMainComponent().add(controlPanel, BorderLayout.NORTH);
		getMainComponent().add(scrollPane, BorderLayout.CENTER);

		setCurrentMonthText(Calendar.getInstance());
	}

	public void addButtonListener(ActionListener listener) {
		increaseMonthButton.addActionListener(listener);
		decreaseMonthButton.addActionListener(listener);
		setCurrentMonthButton.addActionListener(listener);
	}

	public void setCurrentMonthText(Calendar calendar) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MONTH);
		setCurrentMonthButton.setText(dateFormat.format(calendar.getTime()));
	}

	public JComponent getMainComponent() {
		return mainPanel;
	}

	
	//Instead of a dry table, we are using a HeatMap
	//Cells of the table will be in different darkness of blue color
	//If the amount is larger, then a deeper color
	private class HeatMapCellRenderer extends DefaultTableCellRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			if (value.equals(0.0)) {
				return new JLabel();
			} else {
				super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

				setHorizontalAlignment(JLabel.RIGHT);
				DecimalFormat df = new DecimalFormat("#.#");
				setText(df.format(value));

				Double amount = (Double) value;

				if (amount > 200.0) {
					setBackground(new Color(100, 100, 255));
				} else if (amount > 100.0) {
					setBackground(new Color(125, 125, 255));
				} else if (amount > 50.0) {
					setBackground(new Color(150, 150, 255));
				} else if (amount > 20.0) {
					setBackground(new Color(175, 175, 255));
				} else if (amount > 10.0) {
					setBackground(new Color(200, 200, 255));
				} else if (amount > 5.0) {
					setBackground(new Color(225, 225, 255));
				} else {
					setBackground(new Color(240, 240, 255));
				}

				return this;
			}
		}
	}

	private class NullSelectionModel implements ListSelectionModel {
		@Override
		public boolean isSelectionEmpty() {
			return true;
		}

		@Override
		public boolean isSelectedIndex(int index) {
			return false;
		}

		@Override
		public int getMinSelectionIndex() {
			return -1;
		}

		@Override
		public int getMaxSelectionIndex() {
			return -1;
		}

		@Override
		public int getLeadSelectionIndex() {
			return -1;
		}

		@Override
		public int getAnchorSelectionIndex() {
			return -1;
		}

		@Override
		public void setSelectionInterval(int index0, int index1) {
		}

		@Override
		public void setLeadSelectionIndex(int index) {
		}

		@Override
		public void setAnchorSelectionIndex(int index) {
		}

		@Override
		public void addSelectionInterval(int index0, int index1) {
		}

		@Override
		public void insertIndexInterval(int index, int length, boolean before) {
		}

		@Override
		public void clearSelection() {
		}

		@Override
		public void removeSelectionInterval(int index0, int index1) {
		}

		@Override
		public void removeIndexInterval(int index0, int index1) {
		}

		@Override
		public void setSelectionMode(int selectionMode) {
		}

		@Override
		public int getSelectionMode() {
			return SINGLE_SELECTION;
		}

		@Override
		public void addListSelectionListener(ListSelectionListener lsl) {
		}

		@Override
		public void removeListSelectionListener(ListSelectionListener lsl) {
		}

		@Override
		public void setValueIsAdjusting(boolean valueIsAdjusting) {
		}

		@Override
		public boolean getValueIsAdjusting() {
			return false;
		}
	}
}
